home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / s0ftpj / fbsd_sub_udp_input.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  6.6 KB  |  279 lines

  1. /*
  2.  * Name: Simple Example of log for bad packets
  3.  * Date: Fri Feb 18 21:42:57 2000
  4.  * Author: pIGpEN [pigpen@s0ftpj.org, deadhead@sikurezza.org]
  5.  *
  6.  * SoftProject Digital Security for Y2K (www.s0ftpj.org)
  7.  * Sikurezza.org Italian Security MailingList (www.sikurezza.org)
  8.  * 
  9.  * COFFEE-WARE LICENSE - This source code is like "THE BEER-WARE LICENSE" by
  10.  * Poul-Henning Kamp <phk@FreeBSD.ORG> but you can give me in return a coffee.
  11.  * 
  12.  * Tested on: FreeBSD 4.0-19990705-CURRENT FreeBSD 4.0-19990705-CURRENT #6 i386
  13.  */
  14.  
  15. /*
  16.  * *stat structures show you general information... this module gives also  
  17.  * source address for variables of udpstat used in udp_input()... It is only
  18.  * an example... 
  19.  *
  20.  * Feb 10 10:11:13 storpio /kernel UDP: udps_badsum 4 from xxx.xxx.xxx.xxx
  21.  *
  22.  * We know source of a packet with badsum and its number in
  23.  * udpstat.udps_badsum...
  24.  *
  25.  * A cool idea can be log bad packets (at least ip header of these)
  26.  * via pseudo device (a bit like ipl) or via procfs...
  27.  */
  28.  
  29. /*
  30.  * Use a Makefile for kld....
  31.  */
  32.  
  33. #include <sys/param.h>
  34. #include <sys/systm.h>
  35. #include <sys/malloc.h>
  36. #include <sys/mbuf.h>
  37. #include <sys/kernel.h>
  38. #include <sys/proc.h>
  39. #include <sys/socket.h>
  40. #include <sys/socketvar.h>
  41. #include <sys/sysctl.h>
  42. #include <sys/syslog.h>
  43. #include <sys/protosw.h>
  44. #include <net/if.h>
  45. #include <net/route.h>
  46. #include <netinet/in.h>
  47. #include <netinet/in_systm.h>
  48. #include <netinet/in_pcb.h>
  49. #include <netinet/ip.h>
  50. #include <netinet/ip_var.h>
  51. #include <netinet/ip_icmp.h>
  52. #include <netinet/udp.h>
  53. #include <netinet/udp_var.h>
  54.  
  55.  
  56. extern struct     protosw     inetsw[];
  57. extern struct     udpstat     udpstat;
  58. extern int      log_in_vain;
  59. extern struct     inpcbhead     udb;
  60. extern struct     sockaddr_in     udp_in;
  61.  
  62. static void      new_udp_input        __P((register struct mbuf *, int ));
  63. static int      s_load             __P((struct module *, int, void *));
  64. int        badport_bandlim        __P((int));
  65.  
  66. /*
  67.  * saving udp_input() with a funct ptr is not necessary... because it isn't 
  68.  * static so we can access it...
  69.  */
  70.  
  71. static int
  72. s_load (struct module *module, int cmd, void *arg)
  73. {
  74.  int s;
  75.  
  76.  switch(cmd) {
  77.     case MOD_LOAD:
  78.             s = splnet();
  79.             inetsw[ip_protox[IPPROTO_UDP]].pr_input = new_udp_input;
  80.                 splx(s);
  81.             break;
  82.             
  83.     case MOD_UNLOAD:
  84.             s = splnet();
  85.             inetsw[ip_protox[IPPROTO_UDP]].pr_input = udp_input;
  86.             splx(s);
  87.             break;
  88.  }
  89.  
  90.  return 0;
  91. }
  92.  
  93. static moduledata_t s_mod_1 = {
  94.             "udp_mod",
  95.             s_load,
  96.             0
  97. };
  98.  
  99. DECLARE_MODULE(udp_mod, s_mod_1, SI_SUB_PSEUDO, SI_ORDER_ANY);
  100.  
  101. static void 
  102. new_udp_input(m, iphlen)
  103.     register struct mbuf *m;
  104.     int iphlen;
  105. {
  106.     register struct ip *ip;
  107.     register struct udphdr *uh;
  108.     register struct inpcb *inp;
  109.     struct mbuf *opts = 0;
  110.     int len;
  111.     struct ip save_ip;
  112.  
  113.     udpstat.udps_ipackets++;
  114.  
  115.     if (iphlen > sizeof (struct ip)) {
  116.         ip_stripoptions(m, (struct mbuf *)0);
  117.         iphlen = sizeof(struct ip);
  118.     }
  119.  
  120.     ip = mtod(m, struct ip *);
  121.     if (m->m_len < iphlen + sizeof(struct udphdr)) {
  122.         if ((m = m_pullup(m, iphlen + sizeof(struct udphdr))) == 0) {
  123.             udpstat.udps_hdrops++;
  124.             log(LOG_INFO, 
  125.                "UDP: udps_hdrops %ld from %s\n",
  126.                 udpstat.udps_hdrops,
  127.                 inet_ntoa(ip->ip_src));
  128.             return;
  129.         }
  130.         ip = mtod(m, struct ip *);
  131.     }
  132.     uh = (struct udphdr *)((caddr_t)ip + iphlen);
  133.  
  134.     len = ntohs((u_short)uh->uh_ulen);
  135.     if (ip->ip_len != len) {
  136.         if (len > ip->ip_len || len < sizeof(struct udphdr)) {
  137.             udpstat.udps_badlen++;
  138.             log(LOG_INFO,
  139.                 "UDP: udps_badlen %ld from %s\n",
  140.                 udpstat.udps_badlen,
  141.                 inet_ntoa(ip->ip_src));
  142.             goto bad;
  143.         }
  144.         m_adj(m, len - ip->ip_len);
  145.         /* ip->ip_len = len; */
  146.     }
  147.     save_ip = *ip;
  148.  
  149.     if (uh->uh_sum) {
  150.         bzero(((struct ipovly *)ip)->ih_x1, 9);
  151.         ((struct ipovly *)ip)->ih_len = uh->uh_ulen;
  152.         uh->uh_sum = in_cksum(m, len + sizeof (struct ip));
  153.         if (uh->uh_sum) {
  154.             udpstat.udps_badsum++;
  155.             log(LOG_INFO,
  156.                 "UDP: udps_badsum %ld from %s\n",
  157.                 udpstat.udps_badsum,
  158.                 inet_ntoa(ip->ip_src));
  159.             m_freem(m);
  160.             return;
  161.         }
  162.     }
  163.  
  164.     if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr)) ||
  165.         in_broadcast(ip->ip_dst, m->m_pkthdr.rcvif)) {
  166.         struct inpcb *last;
  167.         
  168.         udp_in.sin_port = uh->uh_sport;
  169.         udp_in.sin_addr = ip->ip_src;
  170.         m->m_len -= sizeof (struct udpiphdr);
  171.         m->m_data += sizeof (struct udpiphdr);
  172.  
  173.         last = NULL;
  174.         for (inp = udb.lh_first; inp != NULL; 
  175.                 inp = inp->inp_list.le_next) {
  176.             if (inp->inp_lport != uh->uh_dport)
  177.                 continue;
  178.             if (inp->inp_laddr.s_addr != INADDR_ANY) {
  179.                 if (inp->inp_laddr.s_addr !=
  180.                     ip->ip_dst.s_addr)
  181.                     continue;
  182.             }
  183.             if (inp->inp_faddr.s_addr != INADDR_ANY) {
  184.                 if (inp->inp_faddr.s_addr !=
  185.                     ip->ip_src.s_addr ||
  186.                     inp->inp_fport != uh->uh_sport)
  187.                     continue;
  188.             }
  189.  
  190.             if (last != NULL) {
  191.                 struct mbuf *n;
  192.  
  193.                 if ((n = m_copy(m, 0, M_COPYALL)) != NULL) {
  194.                     if (last->inp_flags & INP_CONTROLOPTS
  195.                         || last->inp_socket->so_options & 
  196.                         SO_TIMESTAMP)
  197.                         ip_savecontrol(last, &opts, ip, n);
  198.                     if (sbappendaddr(&last->inp_socket->so_rcv,
  199.                         (struct sockaddr *)&udp_in,
  200.                         n, opts) == 0) {
  201.                         m_freem(n);
  202.                         if (opts)
  203.                             m_freem(opts);
  204.                         udpstat.udps_fullsock++;
  205.                     } else
  206.                         sorwakeup(last->inp_socket);
  207.                     opts = 0;
  208.                 }
  209.             }
  210.             last = inp;
  211.             if ((last->inp_socket->so_options&(SO_REUSEPORT |
  212.                             SO_REUSEADDR)) == 0)
  213.                 break;
  214.         }
  215.  
  216.         if (last == NULL) {
  217.             udpstat.udps_noportbcast++;
  218.             goto bad;
  219.         }
  220.         if (last->inp_flags & INP_CONTROLOPTS
  221.             || last->inp_socket->so_options & SO_TIMESTAMP)
  222.             ip_savecontrol(last, &opts, ip, m);
  223.         if (sbappendaddr(&last->inp_socket->so_rcv,
  224.              (struct sockaddr *)&udp_in,
  225.              m, opts) == 0) {
  226.             udpstat.udps_fullsock++;
  227.             goto bad;
  228.         }
  229.         sorwakeup(last->inp_socket);
  230.         return;
  231.     }
  232.     inp = in_pcblookup_hash(&udbinfo, ip->ip_src, uh->uh_sport,
  233.         ip->ip_dst, uh->uh_dport, 1);
  234.     if (inp == NULL) {
  235.         if (log_in_vain) {
  236.             char buf[4*sizeof "123"];
  237.  
  238.             strcpy(buf, inet_ntoa(ip->ip_dst));
  239.             log(LOG_INFO,
  240.                 "Connection attempt to UDP %s:%d from %s:%d\n",
  241.                 buf, ntohs(uh->uh_dport), inet_ntoa(ip->ip_src),
  242.                 ntohs(uh->uh_sport));
  243.         }
  244.         udpstat.udps_noport++;
  245.         if (m->m_flags & (M_BCAST | M_MCAST)) {
  246.             udpstat.udps_noportbcast++;
  247.             goto bad;
  248.         }
  249.         *ip = save_ip;
  250.  
  251.         if (badport_bandlim(0) < 0)
  252.             goto bad;
  253.  
  254.         icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PORT, 0, 0);
  255.         return;
  256.     }
  257.  
  258.     udp_in.sin_port = uh->uh_sport;
  259.     udp_in.sin_addr = ip->ip_src;
  260.     if (inp->inp_flags & INP_CONTROLOPTS
  261.         || inp->inp_socket->so_options & SO_TIMESTAMP)
  262.         ip_savecontrol(inp, &opts, ip, m);
  263.     iphlen += sizeof(struct udphdr);
  264.     m->m_len -= iphlen;
  265.     m->m_pkthdr.len -= iphlen;
  266.     m->m_data += iphlen;
  267.     if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&udp_in,
  268.         m, opts) == 0) {
  269.         udpstat.udps_fullsock++;
  270.         goto bad;
  271.     }
  272.     sorwakeup(inp->inp_socket);
  273.     return;
  274. bad:
  275.     m_freem(m);
  276.     if (opts)
  277.         m_freem(opts);
  278. }
  279.